/**
 * FileName: LoginController Author:   zeroleavebaoyang Date:     2018/8/28 11:42 Description:
 */
package com.shiro.sso.demo.web;


import static com.shiro.sso.demo.utils.Platform.*;

import com.alibaba.fastjson.JSONObject;
import com.shiro.sso.demo.model.User;
import com.shiro.sso.demo.oauth2.OAuthInfo;
import com.shiro.sso.demo.utils.Constant;
import com.shiro.sso.demo.utils.HttpUtils;
import com.shiro.sso.demo.utils.OAuthHelper;
import com.shiro.sso.demo.utils.Platform;
import com.shiro.sso.demo.utils.RequestUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ThreadContext;
import org.apache.shiro.web.subject.WebSubject;
import org.apache.shiro.web.subject.WebSubject.Builder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Slf4j
@Controller
public class LoginController {

    @GetMapping({"/", "/index"})
    public String index() {
        return "index";
    }


    @GetMapping("/login")
    public String loginPage(HttpServletRequest req) {
        OAuthInfo baiduOAuthInfo = OAuthHelper.getOauthInfo(baidu);
        req.setAttribute(baidu.toString(), baiduOAuthInfo.getUserInfoAuthUrl());
        return RequestUtils.getSsoUrl(req);
    }

    @PostMapping("/login")
    public String doLogin(HttpServletRequest req, String username, String password) {
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(new UsernamePasswordToken(username, password));
        } catch (UnknownAccountException e) {
            log.error("{}", e);
        } catch (IncorrectCredentialsException e) {
            log.error("{}", e);
        } catch (LockedAccountException e) {
            log.error("{}", e);
        }
        return RequestUtils.getSsoUrl(req);
    }


    @RequestMapping("/third_login/{platform}")
    public String thirdLogin(@PathVariable("platform") String platform, String code,
            HttpServletRequest request, HttpServletResponse response) {
        Platform currentPlatform = null;
        for (Platform pf : values()) {
            if (pf.toString().equals(platform)) {
                currentPlatform = pf;
                break;
            }
        }
        OAuthInfo oAuthInfo = OAuthHelper.getOauthInfo(currentPlatform);
        String tokenUrl = oAuthInfo.getUserInfoTokenUrl(code);
        String ret = HttpUtils.httpGet(tokenUrl);
        JSONObject baiduToken = JSONObject.parseObject(ret);
        String apiUrl = oAuthInfo.getUserInfoApiUrl(baiduToken.getString("access_token"));
        ret = HttpUtils.httpGet(apiUrl);
        JSONObject userJson = JSONObject.parseObject(ret);
        User user = currentPlatform.transformUser(userJson);
        if (user != null) {
            User persistenceUser = findUserByThirdId(user.getThirdId());
            if (persistenceUser == null) {
                insertUser(persistenceUser);
            }
        }
        oAuthLoginSuccess(request, response, user);
        return RequestUtils.getOAuthSuccessUrl(request);
    }

    private void oAuthLoginSuccess(HttpServletRequest request, HttpServletResponse response,
            User user) {
        PrincipalCollection principals = new SimplePrincipalCollection(user, "oauthUser");
        Builder builder = new WebSubject.Builder(request, response);
        builder.principals(principals);
        builder.authenticated(true);
        WebSubject subject = builder.buildWebSubject();
        ThreadContext.bind(subject);
    }


    public static User findUserByThirdId(String thirdId) {
        User u = new User();
        u.setThirdId(thirdId);
        u.setUsername("admin");
        log.info(">>> findUserByThirdId {}", thirdId);
        return u;
    }

    public static void insertUser(User u) {
        log.info(">>> insert user {}", u);
    }
}
